/*
 * Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jef.core.util;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.*;
import lombok.experimental.Accessors;
import org.jef.core.constant.CommonConstants;
import org.jef.core.mask.Eval;
import org.jef.core.properties.BodyEncryProperties;
import org.jef.core.properties.JefProperties;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;

/**
 * 响应信息主体
 *
 * @param <T>
 * @author lengleng
 */
@ToString
@NoArgsConstructor
@Accessors(chain = true)
public class R<T> implements Serializable {

	private static final long serialVersionUID = 1L;

	@Getter
	@Setter
	private int code;

	@Getter
	@Setter
	private String msg;

	@Getter
	@Setter
	private T data;

	@Getter
	@Setter
	@JsonIgnore
	private Class clazz;

	@Getter
	@Setter
	private boolean encryption;

	public R(int code, String msg, T data, Class clazz) {
		this.code = code;
		this.msg = msg;
		this.data = data;
		this.clazz = clazz;
	}

	public static <T> R<T> ok() {
		return restResult(null, CommonConstants.SUCCESS, null);
	}

	public static <T> R<T> ok(T data) {
		return restResult(data, CommonConstants.SUCCESS, null);
	}

	public static <T> R<T> ok(T data, String msg) {
		return restResult(data, CommonConstants.SUCCESS, msg);
	}

	public static <T> R<T> failed() {
		return restResult(null, CommonConstants.FAIL, null);
	}

	public static <T> R<T> failed(String msg) {
		return restResult(null, CommonConstants.FAIL, msg);
	}

	public static <T> R<T> failed(T data) {
		return restResult(data, CommonConstants.FAIL, null);
	}

	public static <T> R<T> failed(T data, String msg) {
		return restResult(data, CommonConstants.FAIL, msg);
	}

	public static <T> R<T> result(T data, int code, String msg) {
		return restResult(data, code, msg);
	}

	public static <T> R<T> restResult(T data, int code, String msg) {
		R<T> apiResult = new R<>();
		apiResult.setCode(code);

		if (data != null && isEncry() ) {
			apiResult.setData((T) encry(data));
			apiResult.setClazz(data.getClass());
			apiResult.setEncryption(true);
		} else {
			apiResult.setData(data);
		}

		apiResult.setMsg(msg);

		return apiResult;
	}

	public Boolean isSuccess() {
		return (this.code == CommonConstants.SUCCESS);
	}

	private static boolean isEncry() {
		JefProperties bean = SpringContextHolder.getBean(JefProperties.class);
		BodyEncryProperties bodyEncry = bean.getBodyencry();
		if (bodyEncry != null) {
			Boolean enable = bodyEncry.getEnabled();
			if (enable != null) {
				return enable;
			}
		}
		return false;
	}
	private static String encry(Object obj) {
		if (obj == null) {
			return null;
		}
		// 序列化
		ObjectMapper bean = SpringContextHolder.getBean(ObjectMapper.class);
		String s = "";
		try {
			s = bean.writeValueAsString(obj);
			JefProperties jefProperties = SpringContextHolder.getBean(JefProperties.class);
			BodyEncryProperties bodyEncry = jefProperties.getBodyencry();
			// 加密
			s = JefAesUtil.getInstance().encrypt(s, bodyEncry.getKey(), bodyEncry.getIv());
		} catch (JsonProcessingException e) {
			throw new RuntimeException(e);
		}
		return s;
	}

}
